home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i011: Getopt program for scripts
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Rich $alz (mirror!rs)
- Mod.sources: Volume 7, Issue 11
- Archive-name: getoptprog
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # Wrapped by mirror!rs on Thu Aug 28 12:55:41 EDT 1986
-
- # Exit status; set to 1 on "wc" errors or if would overwrite.
- STATUS=0
- # Contents: README Makefile getopt.1 getopt.c
-
- echo x - README
- if test -f README ; then
- echo README exists, putting output in $$README
- OUT=$$README
- STATUS=1
- else
- OUT=README
- fi
- sed 's/^XX//' > $OUT <<'@//E*O*F README//'
- XXThis quick throw-off is a public-domain implementation of the USG
- XXgetopt program. Not to be confused with the library routine, this
- XXprogram helps scripts parse their options/flags/arguments.
-
- XXAfter unpacking, tweak the Makefile as appropriate and run make. Copy
- XXthe examples from the manpage into separate files as verify that they
- XXwork ok. Do a "make install". For your final examination, convert
- XXlint to use this program. I write more Makefiles for mod.sources
- XXsubmissions than I care to, and sometimes I get tired of it; I
- XXapologize for the terseness of the one here.
-
- XXIf you don't have getopt(3) in your C run-time library, snip it off
- XXthe tail of the source file, and add it, or make it easily, publicly,
- XXavailable in some other way.
- XX /Rich $alz
- @//E*O*F README//
- chmod u=rw,g=rw,o=rw $OUT
-
- echo x - Makefile
- if test -f Makefile ; then
- echo Makefile exists, putting output in $$Makefile
- OUT=$$Makefile
- STATUS=1
- else
- OUT=Makefile
- fi
- sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//'
- XX# Pick one
- XXCFLAGS = -O -DINDEX=index
- XX#CFLAGS = -O -DINDEX=strchr
- XX# Pick one
- XXM = /usr/man/man1/getopt.1
- XX#M = /usr/man/u_man/man1/getopt.1# Is this path right?
- XX# Where executable ends up; don't forget the trailing /
- XXD = /bin/
-
- XXgetopt: getopt.c
- XX $(CC) $(CFLAGS) -o getopt getopt.c
- XXinstall: getopt
- XX cp getopt $Dgetopt
- XX strip $Dgetopt
- XX cp getopt.1 $M
- @//E*O*F Makefile//
- chmod u=rw,g=rw,o=rw $OUT
-
- echo x - getopt.1
- if test -f getopt.1 ; then
- echo getopt.1 exists, putting output in $$getopt.1
- OUT=$$getopt.1
- STATUS=1
- else
- OUT=getopt.1
- fi
- sed 's/^XX//' > $OUT <<'@//E*O*F getopt.1//'
- XX.TH GETOPT 1 LOCAL
- XX.SH NAME
- XXgetopt \- format flags for shell scripts
- XX.SH SYNOPSIS
- XX.B getopt
- XXflag_spec argument ...
- XX.SH DESCRIPTION
- XX.I Getopt
- XXis a program intended to be called by scripts to ``canonicalize'' their
- XXarguments before processing them, just as the
- XX.IR getopt (3)
- XXroutine does for C programs.
- XX(This need for scripts is usually most noticeable in the way
- XX.IR lint (1)
- XXhandles the
- XX.B \-n
- XXflag.)
- XX.PP
- XXThe following two examples provide the initial parsing for a script
- XXwhich takes two flags,
- XX.B \-a
- XXand
- XX.BR \-b ,
- XXthe second of which takes an argument.
- XX.RS
- XX.ta +4n +4n +4n +4n
- XX.nf
- XX# For /bin/csh...
- XXset argv = (`getopt "ab:" $*`)
- XXif ( $status ) then
- XX echo "Read the documentation and try again." >/dev/tty
- XX exit 1
- XXendif
- XXset Aflag=0
- XXset Name=NONE
- XXwhile "$1" != "--"
- XX switch ("$1")
- XX case '-a':
- XX set Aflag=1
- XX breaksw
- XX case '-b':
- XX shift
- XX set Name=$1
- XX breaksw
- XX endsw
- XX shift
- XXend
- XXshift
- XXecho Aflag=$Aflag / Name=$Name / Remaining args are $*
-
- XX# For /bin/sh...
- XXset -- `getopt "d:s" $@`
- XXif test $? != 0 ; then
- XX echo "Read the documentation and try again."
- XX exit 1
- XXfi
- XXAflag=0
- XXName=NONE
- XXfor f
- XXdo
- XX case "$f" in
- XX -a) Aflag=1
- XX ;;
- XX -b) shift
- XX Name=$2
- XX ;;
- XX --) break
- XX ;;
- XX esac
- XX shift
- XXdone
- XXshift
- XXecho Aflag=$Aflag / Name=$Name / Remaining args are $*
- XX.fi
- XX.RE
- XX.SH DIAGNOSTICS
- XXThe program burps the standard
- XX.IR getopt (3)
- XXdiagnostics to standard error, and exits with a non-zero status if an
- XXerror occurs.
- XXIt is arguable wrong that the diagnostics imply that the program
- XXis named ``getopt'' rather than the real name of the script.
- XXIt is undeniably AT&T\-compatible to do this, however.
- XX.SH "SEE ALSO"
- XXcsh(1), sh(1), getopt(3)
- XX.SH AUTHOR
- XX.nf
- XXRich $alz
- XXMirror Systems
- XX(mirror!rs, rs@mirror.TMC.COM)
- @//E*O*F getopt.1//
- chmod u=rw,g=rw,o=rw $OUT
-
- echo x - getopt.c
- if test -f getopt.c ; then
- echo getopt.c exists, putting output in $$getopt.c
- OUT=$$getopt.c
- STATUS=1
- else
- OUT=getopt.c
- fi
- sed 's/^XX//' > $OUT <<'@//E*O*F getopt.c//'
- XX/*
- XX** GETOPT PROGRAM AND LIBRARY ROUTINE
- XX**
- XX** I wrote main() and AT&T wrote getopt() and we both put our efforts into
- XX** the public domain via mod.sources.
- XX** Rich $alz
- XX** Mirror Systems
- XX** (mirror!rs, rs@mirror.TMC.COM)
- XX** August 10, 1986
- XX*/
-
- XX#include <stdio.h>
-
-
- XX#ifndef INDEX
- XX#define INDEX index
- XX#endif
-
-
- XXextern char *INDEX();
- XXextern int optind;
- XXextern char *optarg;
-
-
- XXmain(ac, av)
- XX register int ac;
- XX register char *av[];
- XX{
- XX register char *flags;
- XX register int c;
-
- XX /* Check usage. */
- XX if (ac < 2) {
- XX fprintf(stderr, "usage: %s flag-specification arg-list\n", av[0]);
- XX exit(2);
- XX }
-
- XX /* Play games; remember the flags (first argument), then splice
- XX them out so it looks like a "standard" command vector. */
- XX flags = av[1];
- XX av[1] = av[0];
- XX av++;
- XX ac--;
-
- XX /* Print flags. */
- XX while ((c = getopt(ac, av, flags)) != EOF) {
- XX if (c == '?')
- XX exit(1);
- XX /* We assume that shells collapse multiple spaces in `` expansion. */
- XX printf("-%c %s ", c, INDEX(flags, c)[1] == ':' ? optarg : "");
- XX }
-
- XX /* End of flags; print rest of options. */
- XX printf("-- ");
- XX for (av += optind; *av; av++)
- XX printf("%s ", *av);
- XX exit(0);
- XX}
- XX
- XX/*
- XX** This is the public-domain AT&T getopt(3) code. I added the
- XX** #ifndef stuff because I include <stdio.h> for the program;
- XX** getopt, per se, doesn't need it. I also added the INDEX/index
- XX** hack (the original used strchr, of course). And, note that
- XX** technically the casts in the write(2) calls shouldn't be there.
- XX*/
-
- XX#ifndef NULL
- XX#define NULL 0
- XX#endif
- XX#ifndef EOF
- XX#define EOF (-1)
- XX#endif
- XX#ifndef INDEX
- XX#define INDEX index
- XX#endif
-
-
- XX#define ERR(s, c) if(opterr){\
- XX extern int strlen(), write();\
- XX char errbuf[2];\
- XX errbuf[0] = c; errbuf[1] = '\n';\
- XX (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
- XX (void) write(2, s, (unsigned)strlen(s));\
- XX (void) write(2, errbuf, 2);}
-
- XXextern int strcmp();
- XXextern char *INDEX();
-
- XXint opterr = 1;
- XXint optind = 1;
- XXint optopt;
- XXchar *optarg;
-
- XXint
- XXgetopt(argc, argv, opts)
- XXint argc;
- XXchar **argv, *opts;
- XX{
- XX static int sp = 1;
- XX register int c;
- XX register char *cp;
-
- XX if(sp == 1)
- XX if(optind >= argc ||
- XX argv[optind][0] != '-' || argv[optind][1] == '\0')
- XX return(EOF);
- XX else if(strcmp(argv[optind], "--") == NULL) {
- XX optind++;
- XX return(EOF);
- XX }
- XX optopt = c = argv[optind][sp];
- XX if(c == ':' || (cp=INDEX(opts, c)) == NULL) {
- XX ERR(": illegal option -- ", c);
- XX if(argv[optind][++sp] == '\0') {
- XX optind++;
- XX sp = 1;
- XX }
- XX return('?');
- XX }
- XX if(*++cp == ':') {
- XX if(argv[optind][sp+1] != '\0')
- XX optarg = &argv[optind++][sp+1];
- XX else if(++optind >= argc) {
- XX ERR(": option requires an argument -- ", c);
- XX sp = 1;
- XX return('?');
- XX } else
- XX optarg = argv[optind++];
- XX sp = 1;
- XX } else {
- XX if(argv[optind][++sp] == '\0') {
- XX sp = 1;
- XX optind++;
- XX }
- XX optarg = NULL;
- XX }
- XX return(c);
- XX}
- @//E*O*F getopt.c//
- chmod u=rw,g=rw,o=rw $OUT
-
- echo Inspecting for damage in transit...
- temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 15 127 756 README
- 15 54 348 Makefile
- 90 292 1707 getopt.1
- 139 436 2832 getopt.c
- 259 909 5643 total
- !!!
- wc README Makefile getopt.1 getopt.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if test -s $dtemp ; then
- echo "Ouch [diff of wc output]:"
- cat $dtemp
- STATUS=1
- elif test $STATUS = 0 ; then
- echo "No problems found."
- else
- echo "WARNING -- PROBLEMS WERE FOUND..."
- fi
- exit $STATUS
-